package stubs;

import interfaces.IMeasure;
import massDistribution.ClassAttributeMap;
import massDistribution.ContinueMeasure;
import massDistribution.DiscreteMeasure;
import massDistribution.MassDistribution;
import massDistribution.MeasuredAttribute;
import core.FrameOfDiscernment;
import engine.Service;

/**
 * This Class is a stub for the  {@link Service}  that allow to retrive the numerical pseudo-random value for the <code>monitoredAttribute<./code>
 * @author  Elisa Costante
 */
public class ServiceStub extends Service {

	/**
	 * @param name
	 */
	public ServiceStub(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	/**
	 * @uml.property  name="probDistribution"
	 * @uml.associationEnd  
	 */
	private ProbabilityDistribution probDistribution;

	/**
	 * @uml.property  name="trustValue"
	 * @uml.associationEnd  
	 */
	private TrustLevel trustValue;

	/**
	 * @return  the probDistribution
	 * @uml.property  name="probDistribution"
	 */
	public ProbabilityDistribution getProbDistribution() {
		return this.probDistribution;
	}

	/**
	 * @param probDistribution
	 *            the probDistribution to set
	 */
	public void setProbDistribution(String probDistribution) {
		if (probDistribution.equalsIgnoreCase(ProbabilityDistribution.NORMAL
				.getLabel())) {
			this.probDistribution = ProbabilityDistribution.NORMAL;
		} else if (probDistribution
				.equalsIgnoreCase(ProbabilityDistribution.BERNOULLI.getLabel())) {
			this.probDistribution = ProbabilityDistribution.BERNOULLI;
		} else if (probDistribution
				.equalsIgnoreCase(ProbabilityDistribution.POISSON.getLabel())) {
			this.probDistribution = ProbabilityDistribution.POISSON;
		}
	}

	/**
	 * @param trustValue
	 *            the trustLevel to set
	 */
	public void setTrustValueFromString(String trustValue) {
		if (trustValue == null) {
			this.trustValue = null;
		} else if (trustValue.equalsIgnoreCase(TrustLevel.LOW.getLabel())) {
			this.trustValue = TrustLevel.LOW;
		} else if (trustValue.equalsIgnoreCase(TrustLevel.MEDIUM.getLabel())) {
			this.trustValue = TrustLevel.MEDIUM;
		} else if (trustValue.equalsIgnoreCase(TrustLevel.HIGH.getLabel())) {
			this.trustValue = TrustLevel.HIGH;
		} else
			this.trustValue = null;
	}

	/**
	 * @return  the trustValue
	 * @uml.property  name="trustValue"
	 */
	public TrustLevel getTrustValue() {
		return this.trustValue;
	}

	/**
	 * @param trustValue  the trustValue to set
	 * @uml.property  name="trustValue"
	 */
	public void setTrustValue(TrustLevel trustValue) {
		this.trustValue = trustValue;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see engine.Service#getMassDistribution(interfaces.Service,
	 * massDistribution.ClassAttributeMap, core.FrameOfDiscernment)
	 */
	@Override
	public MassDistribution getMassDistribution(
			FrameOfDiscernment frameOfDiscernment,
			ClassAttributeMap classAttributeMap) {
		if (measuredAttributes != null) {
			// generate the mass distribution
			for (MeasuredAttribute attribute : measuredAttributes) {
				IMeasure measure = readMeasure(this, attribute);
				attribute.getMetric().setMeasure(measure);
			}

			return super.getMassDistribution(frameOfDiscernment,
					classAttributeMap);
		} else
			return MassDistribution.getLackOfKnowledge(frameOfDiscernment);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see engine.Service#readMeasure(interfaces.Service,
	 * massDistribution.MeasuredAttribute)
	 */

	public IMeasure readMeasure(Service service, MeasuredAttribute attribute) {

		if (measuredAttributes.contains(attribute)) {
			// read the attribute
			MeasuredAttribute attr = getMeasuredAttribute(attribute
					.getIdentifier());
			return attr.getMetric().getMeasure();

		} else {
			switch (attribute.getMetric().getType().getValue()) {
			case 1:
				return ContinueMeasure.NOT_MEASURED;
			case 2:
				return ContinueMeasure.NOT_MEASURED;
			case 3:
				return DiscreteMeasure.NOT_MEASURED;
			default:
				return null;
			}
		}
	}

	/**
	 * Returns the name of the monitored Service with the name
	 * <code>serviceName</code> or null if no servie with the given name exist.
	 * 
	 * @param columnName
	 * @return
	 */
	public ServiceStub getMonitoredService(String serviceName) {
		if (monitoredServices != null) {
			for (int i = 0; i < monitoredServices.size(); i++) {
				ServiceStub service = (ServiceStub) monitoredServices.get(i);
				if (service != null)
					if (service.getIdentifierName().equalsIgnoreCase(
							serviceName))
						return service;
			}
		}
		return null;
	}

	/**
	 * Returns the name of the monitored Service with the name
	 * <code>serviceName</code> or null if no servie with the given name exist.
	 * 
	 * @param columnName
	 * @return
	 */
	public MeasuredAttribute getMeasuredAttribute(String attributeName) {
		if (measuredAttributes != null) {
			for (int i = 0; i < measuredAttributes.size(); i++) {
				MeasuredAttribute attr = (MeasuredAttribute) measuredAttributes
						.get(i);
				if (attr != null)
					if (attr.getIdentifier().equalsIgnoreCase(attributeName))
						return attr;
			}
		}
		return null;
	}

	@Override
	public Object clone() throws CloneNotSupportedException {
		if (this != null && this.getIdentifierName() != null) {

			ServiceStub cloned = new ServiceStub(this.getIdentifierName());
			cloned.setProbDistribution(this.probDistribution);
			cloned.setTrustValue(this.trustValue);

			if (this.measuredAttributes != null) {
				for (MeasuredAttribute attribute : this.measuredAttributes) {
					cloned.addMeasuredAttribute((MeasuredAttribute) attribute
							.clone());
				}
			}
			if (monitoredServices != null) {
				for (Service monitoredService : monitoredServices) {
					cloned.addMonitoredService((Service) monitoredService
							.clone());

				}
			}
			return cloned;

		} else
			return null;
	}

	/**
	 * @param probDistribution  the probDistribution to set
	 * @uml.property  name="probDistribution"
	 */
	public void setProbDistribution(ProbabilityDistribution probDistribution) {
		this.probDistribution = probDistribution;
	}
}
